package com.starsoft.smdc.dao;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.starsoft.frame.core.orm.BaseDao;
import com.starsoft.frame.core.orm.PageObject;
import com.starsoft.frame.util.DateUtil;
import com.starsoft.frame.util.StringUtil;
import com.starsoft.smdc.bean.SmdcEr;
import com.starsoft.smdc.bean.SmdcErId;
import com.starsoft.smdc.bean.SmdcFundamental;
import com.starsoft.smdc.bean.SmdcSecurity;

@Repository
public class ErDao extends BaseDao<SmdcEr, SmdcErId>{
	
	@Autowired
	FundamentalDao fundamentalDao;
	
	public void delete(SmdcEr er){
		fundamentalDao.deleteEr(er);
	}
	
	public void saveOrUpdate(SmdcEr er){
		fundamentalDao.saveEr(er);
	}
	
	public void saveOrUpdate(List<SmdcEr> ers) {
		for (SmdcEr er : ers) {
			saveOrUpdate(er);
		}
	}
	
	public boolean checkCanUpdate(SmdcEr er){
		if(er.getNotUpdate()!=null && er.getNotUpdate()==true){
			return false;
		}
		return true;
	}
	
	public SmdcEr get(SmdcErId id){
 		return fundamentalDao.getEr(id);
	}
	
	public Date getMaxErDate(SmdcSecurity security){
		SmdcFundamental fundamental = fundamentalDao.get(security.getSecId());
		Date maxDate = null;
		for(SmdcEr er : fundamental.getSmdcErs()){
			if(maxDate != null && maxDate.before(er.getId().getReportDate())){
				maxDate = er.getId().getReportDate();
			} else if(maxDate == null){
				maxDate = er.getId().getReportDate();
			}
		}
		return maxDate;
	}

	public List<SmdcEr> getErDateAfter(SmdcSecurity security, Date beginDate){
		SmdcFundamental fundamental = fundamentalDao.get(security.getSecId());
		List<SmdcEr> ers = new ArrayList<SmdcEr>();
		Date beginDateFloor = DateUtil.floorTime(beginDate);
		for(SmdcEr er : fundamental.getSmdcErs()){
			if(!er.getId().getReportDate().before(beginDateFloor)){
				ers.add(er);
			}
		}
		sortErList(ers);
		return ers;
	}

	public SmdcEr getPbDateBeforeOne(SmdcSecurity security, Date publishDate) {
		SmdcFundamental fundamental = fundamentalDao.get(security.getSecId());
		SmdcEr result = null;
		for(SmdcEr er : fundamental.getSmdcErs()){
			if(er.getPublishDate()==null){
				continue;
			}
			if(!er.getPublishDate().after(publishDate)){
				if(result!=null && compareErDateNew(er, result)){
					result = er;
				} else if(result == null){
					result = er;
				}
			}
		}
		return result;
	}

	private boolean compareErDateNew(SmdcEr erA, SmdcEr erB){
		if(erA.getPublishDate().after(erB.getPublishDate())){
			return true;
		} else if(erA.getPublishDate().compareTo(erB.getPublishDate()) == 0){
			return erA.getId().getReportDate().after(erB.getId().getReportDate());
		} else {
			return false;
		}
	}
	
	public List<SmdcEr> getPbDateBeforeN(SmdcSecurity security, Date publishDate, int number) {
		SmdcFundamental fundamental = fundamentalDao.get(security.getSecId());
		List<SmdcEr> result = new ArrayList<SmdcEr>();
		for(SmdcEr er : fundamental.getSmdcErs()){
			if(er.getPublishDate()==null){
				continue;
			}
			if(!er.getPublishDate().after(publishDate)){
				result.add(er);
			}
		}
		sortErList(result);
		int startIndex = result.size() - number;
		if(startIndex<0){
			startIndex= 0;
		}
		return result.subList(startIndex, result.size());
	}

	public Map<String, Object> pageQuery(PageObject po, String secId, Date beginDate, Date endDate) {
		List<Criterion> criterions = new ArrayList<Criterion>();
		String sort = po.getSort().replace("secId", "id.secId").replace("reportDate", "id.reportDate");
		po.setSort(sort);
		if(!StringUtil.isEmpty(secId)){
			criterions.add(Restrictions.like("id.secId", secId, MatchMode.ANYWHERE));
		}
		if(beginDate!=null){
			criterions.add(Restrictions.ge("id.reportDate", beginDate));
		}
		if(endDate!=null){
			criterions.add(Restrictions.le("id.reportDate", endDate));
		}
		return this.pageQuery(entityClass, po, criterions);
	}

	private void sortErList(List<SmdcEr> erList) {
		Collections.sort(erList,
			(SmdcEr o1, SmdcEr o2) -> {
				Date div1 = o1.getId().getReportDate();
				Date div2 = o2.getId().getReportDate();
				if(div1.before(div2)){
					return -1;
				} else if(div1.equals(div2)){
					return 0;
				} else {
					return 1;
				}
			});
	}

}
